package cn.harry.cabinet.view.fragments

import android.Manifest
import android.app.AlertDialog
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import cn.harry.cabinet.R
import cn.harry.cabinet.arcface.faceserver.FaceServer
import cn.harry.cabinet.constants.StorageConstants
import cn.harry.cabinet.databinding.FragmentFeatureLibraryBinding
import cn.harry.cabinet.utils.logConfigChange
import com.arcsoft.face.FaceEngine
import com.arcsoft.face.FaceInfo
import com.arcsoft.face.enums.DetectFaceOrientPriority
import com.arcsoft.face.enums.DetectMode
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.util.*

/**
 * 特征库管理Fragment
 * 用于显示和管理所有用户的特征码信息
 */
class FeatureLibraryFragment : BaseFragment() {

    private var _binding: FragmentFeatureLibraryBinding? = null
    private val binding get() = _binding!!
    private lateinit var featureAdapter: FeatureAdapter
    private val featureList = mutableListOf<FeatureItem>()
    
    // 使用统一的存储路径常量
    private val featureDir: String
        get() = StorageConstants.getFeatureDir(requireContext())
    
    private val imageDir: String
        get() = StorageConstants.getImageDir(requireContext())
    
    // 图片选择器
    private val pickImagesLauncher = registerForActivityResult(
        ActivityResultContracts.GetMultipleContents()
    ) { uris ->
        if (uris.isNotEmpty()) {
            processSelectedImages(uris)
        }
    }
    
    // 文件夹选择器
    private val pickFolderLauncher = registerForActivityResult(
        ActivityResultContracts.OpenDocumentTree()
    ) { uri ->
        uri?.let { processSelectedFolder(it) }
    }
    
    // 权限请求
    private val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        val allGranted = permissions.values.all { it }
        if (allGranted) {
            showBatchRegisterOptions()
        } else {
            showToast("需要存储权限才能批量注册")
        }
    }

    companion object {
        private const val TAG = "FeatureLibraryFragment"
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentFeatureLibraryBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // 初始化RecyclerView
        initRecyclerView()
        
        // 初始化按钮事件
        initButtons()
        
        // 加载特征码数据
        loadFeatureData()
    }

    private fun initRecyclerView() {
        featureAdapter = FeatureAdapter(
            featureList,
            onDeleteClick = { position ->
                deleteFeature(position)
            },
            onCopyClick = { name ->
                copyNameToClipboard(name)
            }
        )
        binding.rvFeatureList.apply {
            layoutManager = LinearLayoutManager(requireContext())
            adapter = featureAdapter
        }
    }

    private fun initButtons() {
        // 批量注册按钮
        binding.btnBatchRegister.setOnClickListener {
            checkPermissionsAndStartBatchRegister()
        }

        // 刷新按钮
        binding.btnRefresh.setOnClickListener {
            loadFeatureData()
        }
        
        // 长按刷新按钮显示调试信息
        binding.btnRefresh.setOnLongClickListener {
            showDebugInfo()
            true
        }
    }

    private fun loadFeatureData() {
        android.util.Log.d(TAG, "开始加载特征码数据")

        // 获取特征码存储目录
        val featureDirFile = File(featureDir)
        if (!featureDirFile.exists()) {
            featureDirFile.mkdirs()
            updateUI()
            return
        }

        // 读取所有特征码文件
        featureList.clear()
        featureDirFile.listFiles()?.forEach { file ->
            if (file.isFile) {
                val name = file.nameWithoutExtension
                val time = file.lastModified()

                // 尝试获取对应的图片文件
                val imgFile = File(imageDir, "$name.jpg")
                val imgPath = if (imgFile.exists()) imgFile.absolutePath else ""

                featureList.add(FeatureItem(name, time, imgPath))
            }
        }

        // 按时间排序
        featureList.sortByDescending { it.time }

        // 更新UI
        updateUI()

        android.util.Log.d(TAG, "特征码数据加载完成，共${featureList.size}条")
    }

    private fun updateUI() {
        // 更新统计信息
        binding.tvTotalCount.text = "总数: ${featureList.size}"
        binding.tvStoragePath.text = "存储路径: ${StorageConstants.getFeatureRootPath(requireContext())}"

        // 更新列表显示
        if (featureList.isEmpty()) {
            showEmptyView()
        } else {
            hideEmptyView()
            featureAdapter.notifyDataSetChanged()
        }
    }

    private fun deleteFeature(position: Int) {
        if (position < 0 || position >= featureList.size) {
            android.util.Log.e(TAG, "Invalid position: $position")
            return
        }

        val featureItem = featureList[position]
        
        AlertDialog.Builder(requireContext())
            .setTitle("删除确认")
            .setMessage("确定要删除特征 '${featureItem.name}' 吗？")
            .setPositiveButton("删除") { _, _ ->
                performDelete(position, featureItem)
            }
            .setNegativeButton("取消", null)
            .show()
    }
    
    private fun performDelete(position: Int, featureItem: FeatureItem) {
        // 删除特征文件
        val featureFile = File(featureDir, featureItem.name)
        if (featureFile.exists()) {
            featureFile.delete()
        }

        // 如果有对应的图片文件，也一并删除
        if (featureItem.imgPath.isNotEmpty()) {
            val imgFile = File(featureItem.imgPath)
            if (imgFile.exists()) {
                imgFile.delete()
            }
        }

        android.util.Log.d(TAG, "删除特征文件: ${featureItem.name}")

        // 从列表中移除项目
        featureList.removeAt(position)

        // 通知适配器数据变化
        featureAdapter.notifyItemRemoved(position)
        featureAdapter.notifyItemRangeChanged(position, featureList.size - position)

        if (featureList.isEmpty()) {
            showEmptyView()
        }
        
        showToast("已删除: ${featureItem.name}")
        
        // 记录删除日志
        requireContext().logConfigChange(
            scope = viewLifecycleOwner.lifecycleScope,
            subType = "FEATURE_DELETE",
            description = "删除人脸特征: ${featureItem.name}",
            oldValue = "存在 - 注册时间: ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date(featureItem.time))}",
            newValue = "已删除"
        )
    }

    /**
     * 复制名称到剪贴板
     */
    private fun copyNameToClipboard(name: String) {
        try {
            val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
            val clip = ClipData.newPlainText("用户名称", name)
            clipboard.setPrimaryClip(clip)
            showToast("名称已复制: $name")
        } catch (e: Exception) {
            android.util.Log.e(TAG, "复制名称失败", e)
            showToast("复制失败")
        }
    }

    private fun showEmptyView() {
        binding.tvEmpty.visibility = View.VISIBLE
        binding.rvFeatureList.visibility = View.GONE
    }

    private fun hideEmptyView() {
        binding.tvEmpty.visibility = View.GONE
        binding.rvFeatureList.visibility = View.VISIBLE
    }
    
    /**
     * 显示调试信息
     */
    private fun showDebugInfo() {
        val debugInfo = buildString {
            append("=== 特征库调试信息 ===\n\n")
            append("特征数量: ${featureList.size}\n")
            append("存储路径: ${StorageConstants.getFeatureRootPath(requireContext())}\n")
            append("特征目录: $featureDir\n")
            append("图片目录: $imageDir\n\n")
            
            val featureDirFile = File(featureDir)
            append("特征目录存在: ${featureDirFile.exists()}\n")
            append("特征目录可读: ${featureDirFile.canRead()}\n")
            append("特征目录可写: ${featureDirFile.canWrite()}\n\n")
            
            val imageDirFile = File(imageDir)
            append("图片目录存在: ${imageDirFile.exists()}\n")
            append("图片目录可读: ${imageDirFile.canRead()}\n")
            append("图片目录可写: ${imageDirFile.canWrite()}\n")
        }

        AlertDialog.Builder(requireContext())
            .setTitle("调试信息")
            .setMessage(debugInfo)
            .setPositiveButton("确定", null)
            .setNeutralButton("复制") { _, _ ->
                val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
                val clip = ClipData.newPlainText("调试信息", debugInfo)
                clipboard.setPrimaryClip(clip)
                showToast("调试信息已复制")
            }
            .show()
    }
    
    /**
     * 检查权限并开始批量注册
     */
    private fun checkPermissionsAndStartBatchRegister() {
        val permissions = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
            arrayOf(Manifest.permission.READ_MEDIA_IMAGES)
        } else {
            arrayOf(
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            )
        }
        
        val allGranted = permissions.all { permission ->
            ContextCompat.checkSelfPermission(requireContext(), permission) == PackageManager.PERMISSION_GRANTED
        }
        
        if (allGranted) {
            showBatchRegisterOptions()
        } else {
            requestPermissionLauncher.launch(permissions)
        }
    }
    
    /**
     * 显示批量注册选项
     */
    private fun showBatchRegisterOptions() {
        val options = arrayOf("从相册选择", "从文件夹选择")
        
        AlertDialog.Builder(requireContext())
            .setTitle("批量注册")
            .setItems(options) { _, which ->
                when (which) {
                    0 -> pickImagesFromGallery()
                    1 -> pickImagesFromFolder()
                }
            }
            .setNegativeButton("取消", null)
            .show()
    }
    
    /**
     * 从相册选择图片
     */
    private fun pickImagesFromGallery() {
        try {
            pickImagesLauncher.launch("image/*")
        } catch (e: Exception) {
            Log.e(TAG, "打开相册失败", e)
            showToast("打开相册失败: ${e.message}")
        }
    }
    
    /**
     * 从文件夹选择图片
     */
    private fun pickImagesFromFolder() {
        try {
            pickFolderLauncher.launch(null)
        } catch (e: Exception) {
            Log.e(TAG, "打开文件夹失败", e)
            showToast("打开文件夹失败: ${e.message}")
        }
    }
    
    /**
     * 处理选中的图片
     */
    private fun processSelectedImages(uris: List<Uri>) {
        lifecycleScope.launch {
            try {
                showToast("开始处理 ${uris.size} 张图片...")
                
                var successCount = 0
                var failCount = 0
                
                for ((index, uri) in uris.withIndex()) {
                    try {
                        // 获取图片文件名作为用户名
                        val userName = getFileNameFromUri(uri) ?: "user_${System.currentTimeMillis()}_$index"
                        Log.d(TAG, "处理图片: $userName, URI: $uri")
                        
                        val bitmap = loadBitmapFromUri(uri)
                        if (bitmap != null) {
                            if (registerFaceFromBitmap(bitmap, userName)) {
                                successCount++
                            } else {
                                failCount++
                            }
                            bitmap.recycle()
                        } else {
                            failCount++
                        }
                    } catch (e: Exception) {
                        Log.e(TAG, "处理图片失败: $uri", e)
                        failCount++
                    }
                }
                
                // 重新加载 FaceServer 特征列表
                withContext(Dispatchers.IO) {
                    FaceServer.getInstance().reloadFaceList(requireContext())
                }
                
                Log.i(TAG, "特征列表重新加载完成")
                showToast("批量注册完成！成功: $successCount, 失败: $failCount")
                loadFeatureData()
                
                // 记录批量注册日志
                requireContext().logConfigChange(
                    scope = viewLifecycleOwner.lifecycleScope,
                    subType = "FEATURE_BATCH_REGISTER",
                    description = "批量注册人脸特征: 总数 ${uris.size}, 成功 $successCount, 失败 $failCount",
                    oldValue = "特征数量: ${featureList.size - successCount}",
                    newValue = "特征数量: ${featureList.size}, 新增: $successCount"
                )
                
            } catch (e: Exception) {
                Log.e(TAG, "批量注册失败", e)
                showToast("批量注册失败: ${e.message}")
            }
        }
    }
    
    /**
     * 处理选中的文件夹
     */
    private fun processSelectedFolder(folderUri: Uri) {
        lifecycleScope.launch {
            try {
                val imageUris = mutableListOf<Uri>()
                
                // 获取文件夹中的所有图片
                val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(
                    folderUri,
                    DocumentsContract.getTreeDocumentId(folderUri)
                )
                
                requireContext().contentResolver.query(
                    childrenUri,
                    arrayOf(DocumentsContract.Document.COLUMN_DOCUMENT_ID, DocumentsContract.Document.COLUMN_MIME_TYPE),
                    null, null, null
                )?.use { cursor ->
                    while (cursor.moveToNext()) {
                        val documentId = cursor.getString(0)
                        val mimeType = cursor.getString(1)
                        
                        if (mimeType?.startsWith("image/") == true) {
                            val documentUri = DocumentsContract.buildDocumentUriUsingTree(folderUri, documentId)
                            imageUris.add(documentUri)
                        }
                    }
                }
                
                if (imageUris.isEmpty()) {
                    showToast("文件夹中没有找到图片")
                    return@launch
                }
                
                processSelectedImages(imageUris)
                
            } catch (e: Exception) {
                Log.e(TAG, "处理文件夹失败", e)
                showToast("处理文件夹失败: ${e.message}")
            }
        }
    }
    
    /**
     * 从 Uri 获取文件名（不含扩展名）
     */
    private fun getFileNameFromUri(uri: Uri): String? {
        try {
            // 尝试从 URI 路径获取文件名
            val path = uri.path
            if (path != null) {
                val fileName = File(path).nameWithoutExtension
                if (fileName.isNotEmpty()) {
                    return fileName
                }
            }
            
            // 尝试从 ContentResolver 获取文件名
            requireContext().contentResolver.query(uri, null, null, null, null)?.use { cursor ->
                if (cursor.moveToFirst()) {
                    val displayNameIndex = cursor.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME)
                    if (displayNameIndex != -1) {
                        val displayName = cursor.getString(displayNameIndex)
                        return displayName.substringBeforeLast('.')
                    }
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "获取文件名失败: $uri", e)
        }
        return null
    }
    
    /**
     * 从 Uri 加载 Bitmap
     */
    private suspend fun loadBitmapFromUri(uri: Uri): Bitmap? = withContext(Dispatchers.IO) {
        try {
            requireContext().contentResolver.openInputStream(uri)?.use { inputStream ->
                val options = BitmapFactory.Options()
                options.inJustDecodeBounds = true
                BitmapFactory.decodeStream(inputStream, null, options)
                
                // 计算缩放比例，限制最大尺寸为 1920x1080
                val maxWidth = 1920
                val maxHeight = 1080
                var scale = 1
                
                while (options.outWidth / scale > maxWidth || options.outHeight / scale > maxHeight) {
                    scale *= 2
                }
                
                Log.d(TAG, "图片原始尺寸: ${options.outWidth}x${options.outHeight}, 缩放比例: $scale")
            }
            
            // 重新打开流并解码
            requireContext().contentResolver.openInputStream(uri)?.use { inputStream ->
                val options = BitmapFactory.Options()
                options.inSampleSize = 1 // 先不缩放，保持原图质量
                BitmapFactory.decodeStream(inputStream, null, options)
            }
        } catch (e: Exception) {
            Log.e(TAG, "加载图片失败: $uri", e)
            null
        }
    }
    
    /**
     * 从 Bitmap 注册人脸
     */
    private suspend fun registerFaceFromBitmap(bitmap: Bitmap, userName: String): Boolean = withContext(Dispatchers.IO) {
        var faceEngine: FaceEngine? = null
        try {
            // 转换为 NV21 格式
            val width = bitmap.width
            val height = bitmap.height
            Log.d(TAG, "处理图片: $userName, 尺寸: ${width}x${height}")
            val nv21 = bitmapToNv21(bitmap, width, height)
            
            // 初始化 FaceEngine
            faceEngine = FaceEngine()
            val initCode = faceEngine.init(
                requireContext(),
                DetectMode.ASF_DETECT_MODE_IMAGE,
                DetectFaceOrientPriority.ASF_OP_0_ONLY,
                16,
                10,
                FaceEngine.ASF_FACE_DETECT or FaceEngine.ASF_FACE_RECOGNITION
            )
            
            if (initCode != 0) {
                Log.e(TAG, "初始化引擎失败: $userName, code: $initCode")
                return@withContext false
            }
            
            // 检测人脸
            val faceInfoList = mutableListOf<FaceInfo>()
            val detectCode = faceEngine.detectFaces(
                nv21,
                width,
                height,
                FaceEngine.CP_PAF_NV21,
                faceInfoList
            )
            
            if (detectCode != 0 || faceInfoList.isEmpty()) {
                Log.w(TAG, "未检测到人脸: $userName, code: $detectCode, faces: ${faceInfoList.size}")
                return@withContext false
            }
            
            // 提取人脸特征
            val faceFeature = com.arcsoft.face.FaceFeature()
            val extractCode = faceEngine.extractFaceFeature(
                nv21,
                width,
                height,
                FaceEngine.CP_PAF_NV21,
                faceInfoList[0],
                faceFeature
            )
            
            if (extractCode != 0) {
                Log.w(TAG, "提取特征失败: $userName, code: $extractCode")
                return@withContext false
            }
            
            // 保存特征到文件
            val featureFile = File(featureDir, userName)
            FileOutputStream(featureFile).use { fos ->
                fos.write(faceFeature.featureData)
            }
            
            // 保存图片
            val imageFile = File(imageDir, "$userName.jpg")
            FileOutputStream(imageFile).use { fos ->
                bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos)
            }
            
            Log.i(TAG, "注册成功: $userName")
            
            // 注意：这里不记录单个注册日志，统一在批量注册完成后记录汇总日志
            true
            
        } catch (e: Exception) {
            Log.e(TAG, "注册人脸失败: $userName", e)
            false
        } finally {
            // 确保释放引擎资源
            faceEngine?.unInit()
        }
    }
    
    /**
     * 将 Bitmap 转换为 NV21 格式
     */
    private fun bitmapToNv21(bitmap: Bitmap, width: Int, height: Int): ByteArray {
        val argb = IntArray(width * height)
        bitmap.getPixels(argb, 0, width, 0, 0, width, height)
        
        val yuv = ByteArray(width * height * 3 / 2)
        encodeYUV420SP(yuv, argb, width, height)
        
        return yuv
    }
    
    /**
     * RGB 转 YUV420SP (NV21)
     */
    private fun encodeYUV420SP(yuv420sp: ByteArray, argb: IntArray, width: Int, height: Int) {
        val frameSize = width * height
        var yIndex = 0
        var uvIndex = frameSize
        
        var R: Int
        var G: Int
        var B: Int
        var Y: Int
        var U: Int
        var V: Int
        
        var index = 0
        for (j in 0 until height) {
            for (i in 0 until width) {
                R = (argb[index] and 0xff0000) shr 16
                G = (argb[index] and 0xff00) shr 8
                B = argb[index] and 0xff
                
                Y = ((66 * R + 129 * G + 25 * B + 128) shr 8) + 16
                U = ((-38 * R - 74 * G + 112 * B + 128) shr 8) + 128
                V = ((112 * R - 94 * G - 18 * B + 128) shr 8) + 128
                
                yuv420sp[yIndex++] = (if (Y < 0) 0 else if (Y > 255) 255 else Y).toByte()
                
                if (j % 2 == 0 && index % 2 == 0) {
                    yuv420sp[uvIndex++] = (if (V < 0) 0 else if (V > 255) 255 else V).toByte()
                    yuv420sp[uvIndex++] = (if (U < 0) 0 else if (U > 255) 255 else U).toByte()
                }
                
                index++
            }
        }
    }
    
    private fun showToast(message: String) {
        Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

/**
 * 特征项数据类
 */
data class FeatureItem(
    val name: String,
    val time: Long,
    val imgPath: String
)

/**
 * 特征列表适配器
 */
class FeatureAdapter(
    private val items: MutableList<FeatureItem>,
    private val onDeleteClick: (Int) -> Unit,
    private val onCopyClick: (String) -> Unit
) : RecyclerView.Adapter<FeatureAdapter.ViewHolder>() {

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val ivFace: ImageView = view.findViewById(R.id.ivFace)
        val tvName: TextView = view.findViewById(R.id.tvName)
        val tvTime: TextView = view.findViewById(R.id.tvTime)
        val btnCopy: ImageButton = view.findViewById(R.id.btnCopy)
        val btnDelete: ImageButton = view.findViewById(R.id.btnDelete)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_feature, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        if (position < 0 || position >= items.size) {
            return
        }

        val item = items[position]
        holder.tvName.text = item.name
        holder.tvTime.text = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
            .format(Date(item.time))

        // 加载人脸图片（如果有）
        if (item.imgPath.isNotEmpty()) {
            BitmapFactory.decodeFile(item.imgPath)?.let { bitmap ->
                holder.ivFace.setImageBitmap(bitmap)
            }
        } else {
            // 设置默认图片
            holder.ivFace.setImageResource(R.drawable.ic_launcher_foreground)
        }

        holder.btnCopy.setOnClickListener {
            onCopyClick(item.name)
        }

        holder.btnDelete.setOnClickListener {
            val currentPosition = holder.adapterPosition
            if (currentPosition != RecyclerView.NO_POSITION && currentPosition < items.size) {
                onDeleteClick(currentPosition)
            }
        }
    }

    override fun getItemCount() = items.size
}